#ifndef TIMER_H
#define TIMER_H

#ifndef u16
#define u16 unsigned short
#endif

#ifndef u32
#define u32 unsigned int
#endif

// Control Registers
#define REG_TM0CNT     *(volatile u16*)0x4000102
#define REG_TM1CNT     *(volatile u16*)0x4000106
#define REG_TM2CNT     *(volatile u16*)0x400010A
#define REG_TM3CNT     *(volatile u16*)0x400010E

// Data Registers
#define REG_TM0D       *(volatile u16*)0x4000100
#define REG_TM1D       *(volatile u16*)0x4000104
#define REG_TM2D       *(volatile u16*)0x4000108
#define REG_TM3D       *(volatile u16*)0x400010C

#define TIMER_FREQUENCY_SYSTEM 	0x0
#define TIMER_FREQUENCY_64 		0x1
#define TIMER_FREQUENCY_256 	0x2
#define TIMER_FREQUENCY_1024 	0x3
#define TIMER_OVERFLOW 			0x4
#define TIMER_ENABLE 			0x80

// Defines what timer slots we are using
#define TIMER_CNT		REG_TM2CNT
#define TIMER_D			REG_TM2D

#define OVERFLOW_CNT	REG_TM3CNT
#define OVERFLOW_D		REG_TM3D

// Set initial counter to 1/4 of 65535.  This should count only up to 1 millisecond before an overflow
#define INITIAL_TIMER_COUNT	-16383

#define MILLISECONDS_PER_OVERFLOW 	1

// Timer Varriables ( don't use these ) //
// Previous Time
static u16 previous_time = 0;
static int elapsed_time_ms = 0;

// Timer Functions //

////////////////////////////////////////////////////////////
// Function: timerInit
// Initializes the Timer and begins timing.
// contrary to the name, this should be called at the end of
// the LoadContent function, right before the game starts.
////////////////////////////////////////////////////////////
void timerInit()
{
    // Set up Timer
    TIMER_D 		= INITIAL_TIMER_COUNT;	// initial value of counting value
    TIMER_CNT 		= TIMER_FREQUENCY_SYSTEM; // set to every 1 cycle, Should be 0.003905231 seconds    
    OVERFLOW_CNT 	= TIMER_ENABLE | TIMER_OVERFLOW;	// enable and set overflow counter to overflow
    TIMER_CNT 		^= TIMER_ENABLE;					// enable the counting timer
}

////////////////////////////////////////////////////////////
// Function: updateTimer
// Updates the timer and adds time to the elpased time
// Should be called every frame before any logic.
////////////////////////////////////////////////////////////
void updateTimer()
{
    // Check the amount of overflows that have occured
    // over the frame
    u16 current_over_flows = OVERFLOW_D;
    
    u16 num_over_flows;
    
    // Check for over flow over flow
    //if ( current_over_flows < previous_time )
    //{
      //  num_over_flows = (u16)(( (u32)current_over_flows + 65535 ) - previous_time);
    //}
    //else
    {
        num_over_flows = current_over_flows - previous_time;
    }

    // Set the previous overflows recorded
    previous_time = current_over_flows;

    // elapsed time in milliseconds
    // is equal to the time it takes
    // for 1 cycle ( 3 milliseconds )
    // multiplied by the number of flows
    // that happened in the previous frame
    elapsed_time_ms = MILLISECONDS_PER_OVERFLOW * num_over_flows;
}

////////////////////////////////////////////////////////////
// Function: getElapsedTime
// Returns the elapsed time since the last timer update
////////////////////////////////////////////////////////////
int getElapsedTime()
{
    return elapsed_time_ms;
}

#endif

